package com.qilin.hammer.util;
import java.io.*;
import java.util.regex.*;

public class FileFinder {

	private String regex;
	private String currentDir;
	private String outputType;
	private Pattern filePattern;
	private Pattern keyPattern;
	
	private String destination;
//	private class listfilter implements FilenameFilter{
//		public boolean accept(File f, String fname){
//			return Pattern.compile(regex).matcher(fname).matches();
//		}
//	}
	
	public FileFinder(){}
	
	private void print(int prefixnum, String output){
		for(int i=0;i<prefixnum;i++)
			output="          "+output;
		System.out.println(output);
	}
	
	private void view(int depth, File currentFile){
		String name = currentFile.getName();
		name=currentFile.isDirectory()?"+ "+name:name;
		if(regex==null)
			print(depth, name);
		else if(currentFile.isDirectory())
			print(depth, name);
		else if(Pattern.compile(regex).matcher(name).matches())
			print(depth, name);
		if(currentFile.isDirectory()){
			File[] filelist = currentFile.listFiles();
			for(File f:filelist){			
					view(depth+1,f);
			}
		}			
	}
	
	private void constructMathcher(String fileRegex, String dirRegex){
		if(null != fileRegex) this.filePattern = Pattern.compile(fileRegex);
		if(null != dirRegex) this.keyPattern = Pattern.compile(dirRegex);
	}
	
	/**
	 * Change the directory used in viewDirectory method
	 * @param dir
	 */
	private void setDirectory(String dir){
		this.currentDir=dir.replaceAll("\\\\","/" );
	}
	
	/**
	 * list all files in the directory 
	 * @param directory
	 */
	public void viewDirectory(String directory){
		this.regex = null;
		this.setDirectory(directory);
		this.view(0, new File(this.currentDir));
	}
	
	/**
	 * list all files with names which match the given regex in the directory
	 * @param directory
	 * @param regex
	 */
	public void viewDirectory(String directory, String regex){
		this.regex=regex;
		this.setDirectory(directory);
		this.view(0, new File(this.currentDir));
	}
	
	private void lookup(File file){
		try {
			BufferedReader br = new BufferedReader(new FileReader(file.getAbsoluteFile()));
			String linetext = null;
			Matcher keyMatcher = null;
			int linenum = 0;
			String result = "";
			while((linetext=br.readLine())!=null){
				linenum++;
				keyMatcher = this.keyPattern.matcher(linetext);
				String findsubstr = null;				
				if( keyMatcher.find()){
					if(this.outputType.equals("-l")){
						findsubstr = keyMatcher.group();
						int leftto = linetext.indexOf(findsubstr);
						int tolast = leftto+findsubstr.length();
						result+="Line "+linenum+":"+linetext.substring(0, leftto)+"["+findsubstr+"]"+linetext.substring(tolast)+"\r\n";
					}else{
						print(0, file.getPath());
						break;
					}
				}	
			}
			if(!result.equals(""))
				print(0, "Found in file "+file.getPath()+":\r\n"+result);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}	
	
	private void copy(File src, String destname){
		try{   
            int bytesum = 0;   
            int byteread = 0;   
            if(src.exists()){     
               InputStream inStream = new FileInputStream(src);    
               FileOutputStream fs = new FileOutputStream(destname);   
               byte[] buffer = new byte[1444];   
               while((byteread = inStream.read(buffer))!= -1){   
                      bytesum += byteread;                     
                      fs.write(buffer, 0, byteread);   
               }   
               System.out.println(bytesum);
               inStream.close();
               fs.close();
            }
		}catch(Exception e){
            System.out.println("error");   
            e.printStackTrace();   
		}    
	}
	
	private void searchandcopy(File currentFile){
		String name = currentFile.getName();
		if(this.filePattern.matcher(name).matches()){
			if(currentFile.isFile()){
				print(0, currentFile.getPath());
				this.copy(currentFile, this.destination+"/"+currentFile.getName());
			}
		}
		if(currentFile.isDirectory()){
			File[] filelist = currentFile.listFiles();
			for(File f:filelist)		
				searchandcopy(f);
		}
	}
	
	private void search(File currentFile, boolean isFindInFile){
		String name = currentFile.getName();
		if(this.filePattern.matcher(name).matches()){
			if(isFindInFile){
				if(currentFile.isFile())
					this.lookup(currentFile);
			}else{
				print(0, currentFile.getPath());
			}
		}
		if(currentFile.isDirectory()){
			File[] filelist = currentFile.listFiles();
			for(File f:filelist)		
				search(f, isFindInFile);
		}
	}
	
	/**
	 * Search all files in give fileRegex to find the key given by strRegex in the given directory. 
	 * And you can use -l or -f parameter to decide to list the line found or the file name
	 * @param directory
	 * @param fileRegex
	 * @param strRegex
	 * @param outputType
	 */
	public void findInFile(String directory, String fileRegex, String strRegex, String outputType){
		this.setDirectory(directory);
		this.constructMathcher(fileRegex, strRegex);
		this.outputType = outputType;
		this.search(new File(this.currentDir), true);
	}
	
	
	public void findFile(String directory, String fileRegex){
		this.setDirectory(directory);
		this.constructMathcher(fileRegex, null);
		this.search(new File(this.currentDir), false);
	}
	
	public void copyfile(String source, String fileRegex, String dest){
		this.setDirectory(source);
		this.constructMathcher(fileRegex, null);
		this.destination = dest;
		this.searchandcopy(new File(this.currentDir));
	}
	
	public static void compareFile(String f1, String f2){
		try{   
            int byteread1 = 0;
            int byteread2 = 0;
            File file1 = new File(f1);
            File file2 = new File(f2);
            if(file1.exists()&& file2.exists() && file1.length() == file2.length()){     
               InputStream inStream1 = new FileInputStream(file1);
               InputStream inStream2 = new FileInputStream(file2);
               byte[] buffer1 = new byte[1444];
               byte[] buffer2 = new byte[1444];
               Loop:
               while((byteread1 = inStream1.read(buffer1))!= -1 && (byteread2 = inStream2.read(buffer2))!= -1){   
                     if(byteread1 != byteread2 || buffer1.length != buffer2.length){
                    	 System.out.println("Not match");
                    	 break;
                     } else{
                    	 for(int i=0; i<buffer1.length; i++){
                    		 if(buffer1[i]!= buffer2[i]){
                    			 System.out.println("Not match");
                            	 break Loop;
                    		 }
                    	 }
                     }
               }
               System.out.println("Match");
               inStream1.close();
               inStream2.close();
            } else {
               System.out.println("Not match");
            }
		}catch(Exception e){
            System.out.println("error");   
            e.printStackTrace();   
		}    
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FileFinder viewer=new FileFinder();
		String dir=null, fileRegex=null, keyRegex=null, param=null;
		if(args.length == 2){
			dir = args[0];
			fileRegex = args[1];
			viewer.findFile(dir, fileRegex);
			System.out.println("Done!");
		}else if(args.length == 4){
			dir = args[0];
			fileRegex = args[1];
			keyRegex = args[2];
			param = args[3];
			viewer.findInFile(dir, fileRegex, keyRegex, param);
			System.out.println("Done!");
		}
//		else if(args.length == 0){
//			viewer.copyfile("D:/personal/restlet-jse-2.0.8/restlet-jse-2.0.8/lib", ".*\\.jar", "D:/temp1");
//			//"D:/personal/restlet-jse-2.0.8/restlet-jse-2.0.8/lib"
//		}
		else{
			System.out.println("usage: input dir, fileRegex to find file in dir, or input dir, fileRegex, keyRegex, param" +
					" to find key in files of dir.");
		}
		//FileFinder.compareFile("D:/work/main/yoda/export/home/applications/sdk/app/bin/sample/dist/com.vitria.app.sample.service.jar", 
			//	"D:/work/main/yoda/export/home/applications/sdk/app/bin/sample/dist/Copy of com.vitria.app.sample.service.jar");
		//viewer.viewDirectory(".");
		//viewer.viewDirectory("D:/work/sdk4test/yoda/bw",".*\\.java");
		//viewer.findInFile("D:\\Oracle\\product\\10.1.0", ".*", "tnsnames\\.ora", "-l");
		viewer.findFile("D:\\Oracle\\product\\10.1.0", "tnsnames\\.ora");
	}

}
